//
//  ViewController.m
//  JKKVO
//
//  Created by 王冲 on 2018/6/14.
//  Copyright © 2018年 JK科技有限公司. All rights reserved.


#import "ViewController.h"
#import "JKPerson.h"
#import <objc/runtime.h>
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

}

#pragma mark 添加KVO和未添加KVO 打印类对象的方法
-(void)print2{
    
    JKPerson *person1 = [[JKPerson alloc]init];
    person1.height = 174;
    
    JKPerson *person2 = [[JKPerson alloc]init];
    person2.height = 178;
    
    NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
    /**
     - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
     observer: 监听的对象
     keyPath:  监听的属性
     options:  监听哪些变化
     context:  附加参数
     控制器对象self 监听 person1 的属性 height 的改变
     */
    [person1 addObserver:self forKeyPath:@"height" options:options context:nil];
    
    [self printMethods:object_getClass(person1)];
    [self printMethods:object_getClass(person2)];
    
    person1.height = 180;
    
    [person1 removeObserver:self forKeyPath:@"height"];
}


#pragma mark 打印添加KVO之前 的内存地址和 添加KVO之后的内存地址 和  打印添加KVO之前 的类对象和 添加KVO之后的类对象
-(void)print1{
    
    JKPerson *person1 = [[JKPerson alloc]init];
    person1.height = 174;
    
    JKPerson *person2 = [[JKPerson alloc]init];
    person2.height = 178;
    
    NSLog(@"person1添加KVO之前 %p %p",[person1 methodForSelector:@selector(setHeight:)],[person2 methodForSelector:@selector(setHeight:)]);
    
    NSLog(@"person1添加KVO之前 person1Class=%@ person2Class=%@",object_getClass(person1),object_getClass(person2));
    
    
    NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
    
    /**
     - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
     observer: 监听的对象
     keyPath:  监听的属性
     options:  监听哪些变化
     context:  附加参数
     控制器对象self 监听 person1 的属性 height 的改变
     */
    [person1 addObserver:self forKeyPath:@"height" options:options context:nil];
    
    [self printMethods:object_getClass(person1)];
    [self printMethods:object_getClass(person2)];
    
    
    NSLog(@"person1添加KVO之后 %p %p",[person1 methodForSelector:@selector(setHeight:)],[person2 methodForSelector:@selector(setHeight:)]);
    
    NSLog(@"person1添加KVO之后 person1Class=%@ person2Class=%@",object_getClass(person1),object_getClass(person2));
    
    person1.height = 180;
    
    [person1 removeObserver:self forKeyPath:@"height"];
}

/**
    KVO监听器实现的方法
 */
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    
    NSLog(@"%@ 的 %@ 属性值从 %@ 变为 %@ ",object,keyPath,change[@"old"],change[@"new"]);
    
}

#pragma mark 打印类对象的 对象方法
-(void)printMethods:(Class)cls{
    
    unsigned int count;
    Method *methods = class_copyMethodList(cls, &count);
    
    NSMutableString *methodNames = [NSMutableString string];
    [methodNames appendFormat:@" [%@] ",cls];
    
    for (int i = 0; i < count; i++) {
        
        Method method = methods[i];
        
        NSString *methodName = NSStringFromSelector(method_getName(method));
        [methodNames appendString:methodName];
        [methodNames appendString:@" "];
    }
    
    NSLog(@"%@",methodNames);
    
    free(methods);
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end
